#pragma once

#include "SharedHandle.h"
#include "SimpleCriticalSection.h"
#include "TimeValue.h"

namespace RoomFW {

//
// Class:	SimpleWaitableTimer
//
// Description:	Simple windows waitable timer wrapper.
//
// Author:	Andrew Sage
//
class SimpleWaitableTimer
{
public:

	//
	// Method:	SimpleWaitableTimer
	//
	// Description:	Constructor
	//
	// Parameters:	None
	//
	SimpleWaitableTimer(void);

	//
	// Method:	SimpleWaitableTimer
	//
	// Description:	Copy Constructor
	//
	// Parameters:	None
	//
	SimpleWaitableTimer(const SimpleWaitableTimer& rhs);

	//
	// Method:	~SimpleWaitableTimer
	//
	// Description:	Destructor
	//
	~SimpleWaitableTimer(void);

	//
	// Method:	operator=
	//
	// Description:	assignment operator
	//
	// Parameters:	None
	//
	SimpleWaitableTimer& operator=(const SimpleWaitableTimer& rhs);

	//
	// Method:	operator HANDLE()
	//
	// Description:	Allow implicit cast to contained HANDLE.
	//
	// Parameters:	None
	//
	// Return:	handle_
	//
	operator HANDLE() const;

	//
	// Method:	create
	//
	// Description:	Create the waitable timer.
	//
	// Parameters:
	//
	//	manualReset -	If this parameter is TRUE, the timer is a manual-reset notification timer.
	//					Otherwise, the timer is a synchronization timer.  See ::CreateWaitableTimer()
	//
	// Return:	Success.
	//
	bool create(bool manualReset = false);

	//
	// Method:	set
	//
	// Description:	Set the timer
	//
	// Parameters:
	//
	//	expireIn - Timeout until first expiration.
	//
	//	repeatEvery - Timeout for subsequent expirations.  Zero for one-shot.
	//
	// Return:	success.
	//
	bool set(const TimeValue& expireIn, const TimeValue& repeatEvery = 0);

	//
	// Method:	set
	//
	// Description:	Set the timer
	//
	// Parameters:
	//
	//	dueTime - See ::SetWaitableTimer()
	//
	//	period - See ::SetWaitableTimer()
	//
	// Return:	success.
	//
	bool set(const LARGE_INTEGER* dueTime, LONG period);

	//
	// Method:	cancel
	//
	// Description:	Cancel the timer.
	//
	// Parameters:	None.
	//
	// Return:	none.
	//
	void cancel(void);

	//
	// Method:	wait
	//
	// Description:	Wait for the timer to be signaled.
	//
	// Parameters:
	//
	//	timeout - Time (in milliseconds) to wait.
	//
	// Return:	true if the timer is signaled with no errors.
	//
	bool wait(DWORD timeout = INFINITE);

private:

	//
	// Deleter to cancel the timer before closing the handle.
	//
	struct TimerHandleDeleter
	{
		void operator()(HANDLE handle);
	};

	//
	// Event handle.
	//
	SharedHandle handle_;

	//
	// Event handle synchronization.
	//
	mutable SimpleCriticalSection cs_;
};

}
